home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume23 / xmodem3.9 / part02 < prev    next >
Encoding:
Internet Message Format  |  1991-01-08  |  51.7 KB

  1. Subject:  v23i078:  Xmodem file transfer program, revision3.9, Part02/03
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: ffcae8d0 3b7d238f b56d60dd c3abc1a3
  5.  
  6. Submitted-by: Steve Grandi <grandi@noao.edu>
  7. Posting-number: Volume 23, Issue 78
  8. Archive-name: xmodem3.9/part02
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then feed it
  12. # into a shell via "sh file" or similar.  To overwrite existing files,
  13. # type "sh file -c".
  14. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  15. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  16. # Contents:  getput.c getput.sysv.c send.c update.doc
  17. # Wrapped by rsalz@litchi.bbn.com on Wed Dec  5 12:31:57 1990
  18. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  19. echo If this archive is complete, you will see the following message:
  20. echo '          "shar: End of archive 2 (of 3)."'
  21. if test -f 'getput.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'getput.c'\"
  23. else
  24.   echo shar: Extracting \"'getput.c'\" \(12356 characters\)
  25.   sed "s/^X//" >'getput.c' <<'END_OF_FILE'
  26. X/*
  27. X * Contains system routines to get and put bytes, change tty modes, etc
  28. X * Most of the routines are VERY 4.2BSD Specific!!!
  29. X */
  30. X
  31. X#include "xmodem.h"
  32. X
  33. X/*
  34. X *
  35. X *    Get a byte from the specified file.  Buffer the read so we don't
  36. X *    have to use a system call for each character.
  37. X *
  38. X */
  39. Xgetbyte(fildes, ch)                /* Buffered disk read */
  40. Xint fildes;
  41. Xchar *ch;
  42. X
  43. X    {
  44. X    static char buf[BUFSIZ];    /* Remember buffer */
  45. X    static char *bufp = buf;    /* Remember where we are in buffer */
  46. X    
  47. X    if (nbchr == 0)            /* Buffer exausted; read some more */
  48. X        {
  49. X        if ((nbchr = read(fildes, buf, BUFSIZ)) < 0)
  50. X            error("File Read Error", TRUE);
  51. X        bufp = buf;        /* Set pointer to start of array */
  52. X        }
  53. X    if (--nbchr >= 0)
  54. X        {
  55. X        *ch = *bufp++;
  56. X        return(0);
  57. X        }
  58. X    else
  59. X        {
  60. X        return(EOF);
  61. X        }
  62. X    }
  63. X
  64. X/* Count the number of newlines in a file so we know the REAL file size */
  65. X
  66. Xlong
  67. Xcountnl(fd)
  68. Xint fd;
  69. X{
  70. X    char buf[BUFSIZ];
  71. X    char *bufp;
  72. X    long nltot = 0;
  73. X    int numchar;
  74. X    long lseek();
  75. X
  76. X    while (numchar = read(fd, buf, BUFSIZ))        /* cycle through file */
  77. X        for (bufp=buf; numchar--; bufp++)
  78. X            if (*bufp == '\n')
  79. X                nltot++;
  80. X
  81. X    (void) lseek (fd, 0l, 0);            /* rewind file */
  82. X    if (DEBUG)
  83. X        fprintf(LOGFP, "DEBUG: countnl--%ld newlines counted\n", nltot);
  84. X    return (nltot);
  85. X}
  86. X
  87. X/*   CRC-16 constant array...
  88. X     from Usenet contribution by Mark G. Mendel, Network Systems Corp.
  89. X     (ihnp4!umn-cs!hyper!mark)
  90. X*/
  91. X
  92. X/* crctab as calculated by initcrctab() */
  93. Xunsigned short crctab[1<<B] = { 
  94. X    0x0000,  0x1021,  0x2042,  0x3063,  0x4084,  0x50a5,  0x60c6,  0x70e7,
  95. X    0x8108,  0x9129,  0xa14a,  0xb16b,  0xc18c,  0xd1ad,  0xe1ce,  0xf1ef,
  96. X    0x1231,  0x0210,  0x3273,  0x2252,  0x52b5,  0x4294,  0x72f7,  0x62d6,
  97. X    0x9339,  0x8318,  0xb37b,  0xa35a,  0xd3bd,  0xc39c,  0xf3ff,  0xe3de,
  98. X    0x2462,  0x3443,  0x0420,  0x1401,  0x64e6,  0x74c7,  0x44a4,  0x5485,
  99. X    0xa56a,  0xb54b,  0x8528,  0x9509,  0xe5ee,  0xf5cf,  0xc5ac,  0xd58d,
  100. X    0x3653,  0x2672,  0x1611,  0x0630,  0x76d7,  0x66f6,  0x5695,  0x46b4,
  101. X    0xb75b,  0xa77a,  0x9719,  0x8738,  0xf7df,  0xe7fe,  0xd79d,  0xc7bc,
  102. X    0x48c4,  0x58e5,  0x6886,  0x78a7,  0x0840,  0x1861,  0x2802,  0x3823,
  103. X    0xc9cc,  0xd9ed,  0xe98e,  0xf9af,  0x8948,  0x9969,  0xa90a,  0xb92b,
  104. X    0x5af5,  0x4ad4,  0x7ab7,  0x6a96,  0x1a71,  0x0a50,  0x3a33,  0x2a12,
  105. X    0xdbfd,  0xcbdc,  0xfbbf,  0xeb9e,  0x9b79,  0x8b58,  0xbb3b,  0xab1a,
  106. X    0x6ca6,  0x7c87,  0x4ce4,  0x5cc5,  0x2c22,  0x3c03,  0x0c60,  0x1c41,
  107. X    0xedae,  0xfd8f,  0xcdec,  0xddcd,  0xad2a,  0xbd0b,  0x8d68,  0x9d49,
  108. X    0x7e97,  0x6eb6,  0x5ed5,  0x4ef4,  0x3e13,  0x2e32,  0x1e51,  0x0e70,
  109. X    0xff9f,  0xefbe,  0xdfdd,  0xcffc,  0xbf1b,  0xaf3a,  0x9f59,  0x8f78,
  110. X    0x9188,  0x81a9,  0xb1ca,  0xa1eb,  0xd10c,  0xc12d,  0xf14e,  0xe16f,
  111. X    0x1080,  0x00a1,  0x30c2,  0x20e3,  0x5004,  0x4025,  0x7046,  0x6067,
  112. X    0x83b9,  0x9398,  0xa3fb,  0xb3da,  0xc33d,  0xd31c,  0xe37f,  0xf35e,
  113. X    0x02b1,  0x1290,  0x22f3,  0x32d2,  0x4235,  0x5214,  0x6277,  0x7256,
  114. X    0xb5ea,  0xa5cb,  0x95a8,  0x8589,  0xf56e,  0xe54f,  0xd52c,  0xc50d,
  115. X    0x34e2,  0x24c3,  0x14a0,  0x0481,  0x7466,  0x6447,  0x5424,  0x4405,
  116. X    0xa7db,  0xb7fa,  0x8799,  0x97b8,  0xe75f,  0xf77e,  0xc71d,  0xd73c,
  117. X    0x26d3,  0x36f2,  0x0691,  0x16b0,  0x6657,  0x7676,  0x4615,  0x5634,
  118. X    0xd94c,  0xc96d,  0xf90e,  0xe92f,  0x99c8,  0x89e9,  0xb98a,  0xa9ab,
  119. X    0x5844,  0x4865,  0x7806,  0x6827,  0x18c0,  0x08e1,  0x3882,  0x28a3,
  120. X    0xcb7d,  0xdb5c,  0xeb3f,  0xfb1e,  0x8bf9,  0x9bd8,  0xabbb,  0xbb9a,
  121. X    0x4a75,  0x5a54,  0x6a37,  0x7a16,  0x0af1,  0x1ad0,  0x2ab3,  0x3a92,
  122. X    0xfd2e,  0xed0f,  0xdd6c,  0xcd4d,  0xbdaa,  0xad8b,  0x9de8,  0x8dc9,
  123. X    0x7c26,  0x6c07,  0x5c64,  0x4c45,  0x3ca2,  0x2c83,  0x1ce0,  0x0cc1,
  124. X    0xef1f,  0xff3e,  0xcf5d,  0xdf7c,  0xaf9b,  0xbfba,  0x8fd9,  0x9ff8,
  125. X    0x6e17,  0x7e36,  0x4e55,  0x5e74,  0x2e93,  0x3eb2,  0x0ed1,  0x1ef0
  126. X    };
  127. X
  128. X/* get a byte from data stream -- timeout if "seconds" elapses */
  129. X/* This routine is VERY 4.2 specific */
  130. X
  131. Xint
  132. Xreadbyte(seconds)
  133. Xint seconds;
  134. X    {
  135. X    int readfd;
  136. X    char c;
  137. X    struct timeval tmout;
  138. X
  139. X    tmout.tv_sec = seconds;
  140. X    tmout.tv_usec = 0;
  141. X
  142. X    readfd = 1<<0;
  143. X
  144. X    if ((select(1, &readfd, (int *)0, (int *)0, &tmout)) == 0)
  145. X        {
  146. X        if (DEBUG)
  147. X            fprintf(LOGFP, "DEBUG: readbyte TIMEOUT\n");
  148. X        return(TIMEOUT);
  149. X        }
  150. X
  151. X    read(0, &c, 1);
  152. X
  153. X    if (DEBUG)
  154. X        fprintf(LOGFP, "DEBUG: readbyte %02xh\n", c & 0xff);
  155. X
  156. X    return(c & 0xff);  /* return the char */
  157. X    }
  158. X
  159. X/* flush input stream by reading pending characters */
  160. X
  161. Xflushin()
  162. X    {
  163. X    int readfd;
  164. X    char inbuf[BBUFSIZ];
  165. X    struct timeval tmout;
  166. X
  167. X    /* set up a usec timeout on stdin */
  168. X    tmout.tv_sec = 0;
  169. X    tmout.tv_usec = 1;
  170. X    readfd = 1<<0;
  171. X
  172. X    /* any characters pending?; return if none */
  173. X    if ((select(1, &readfd, (int *)0, (int *)0, &tmout)) == 0)
  174. X        return;
  175. X
  176. X    /* read the characters to flush them (assume there are fewer than BBUFSIZ */
  177. X    (void) read(0, inbuf, BBUFSIZ);
  178. X    }
  179. X
  180. X/* 
  181. X get a buffer (length bufsize) from data stream -- timeout if "seconds" elapses.
  182. X Read bunches of characters to save system overhead;
  183. X Further process data while kernel is reading stream (calculating "checksum").
  184. X Try to nap long enough so kernel collects 100 characters or so until we wake up
  185. X unless TOOBUSY is set.
  186. X*/
  187. X
  188. X/* This routine is VERY 4.2 specific */
  189. X
  190. Xint
  191. Xreadbuf(bufsize, seconds, tmode, amode, recvsectcnt, checksum, bufctr)
  192. X
  193. Xint bufsize,    /* number of chars to be read */
  194. Xseconds,     /* timeout period for each read */
  195. Xtmode,         /* transmission mode: TRUE if text */
  196. Xamode,         /* transmission mode: TRUE if apple macintosh */
  197. X*checksum,     /* pointer to checksum value */
  198. X*bufctr;    /* length of actual data string in buffer */
  199. Xlong recvsectcnt;    /* running sector count (128 byte sectors) */
  200. X
  201. X{
  202. X    int readfd;        /* mask for select call */
  203. X    struct timeval tmout;    /* timeout structure for select */
  204. X    int numread;        /* number of chars read */
  205. X    int left;        /* number of chars left to read */
  206. X    int recfin = FALSE;        /* flag that EOF read */
  207. X    char inbuf[BBUFSIZ];    /* buffer for incoming packet */
  208. X    register unsigned char c;    /* character being processed */
  209. X    register unsigned short chksm;    /* working copy of checksum */
  210. X    register int bfctr;    /* working copy of bufctr */
  211. X    int j;            /* loop index */
  212. X    char *sectdisp();
  213. X
  214. X    tmout.tv_sec = seconds;
  215. X    tmout.tv_usec = 0;
  216. X    readfd = 1<<0;
  217. X    chksm = 0;
  218. X    bfctr = 0;
  219. X
  220. X    for (left = bufsize; left > 0;) {
  221. X
  222. X        /* read however many chars are waiting */
  223. X
  224. X        if ((select(1, &readfd, (int *)0, (int *)0, &tmout)) == 0)
  225. X            return(TIMEOUT);
  226. X
  227. X        numread = read(0, inbuf, left);
  228. X        left -= numread;
  229. X
  230. X        if (DEBUG)
  231. X            fprintf(LOGFP, "DEBUG: readbuf--read %d characters\n", numread);
  232. X
  233. X        /* now process part of packet we just read */
  234. X
  235. X        for (j =  0; j < numread; j++) 
  236. X            {  
  237. X                buff[bfctr] = c = inbuf[j] & 0xff;
  238. X                fileread++;
  239. X
  240. X                if (CRCMODE)  /* CRC */
  241. X                    chksm = (chksm<<B) ^ crctab[(chksm>>(W-B)) ^ c];
  242. X
  243. X                else        /* checksum */
  244. X                           chksm = ((chksm+c) & 0xff);
  245. X
  246. X                if (CHECKLENGTH && fileread > filelength)    /* past EOF ? */
  247. X                    continue;
  248. X
  249. X                if (tmode)         /* text mode processing */
  250. X                    {
  251. X                    buff[bfctr] &= 0x7f;    /* nuke bit 8 */
  252. X                    if (c == CR || c == 0)    /* skip CRs and nulls */
  253. X                        continue;
  254. X                    else if (c == CTRLZ)    /* CP/M EOF char */
  255. X                        {  
  256. X                        recfin = TRUE;
  257. X                               continue;
  258. X                               }
  259. X                           else if (!recfin)    /* don't increment if past EOF */
  260. X                        bfctr++;
  261. X                    }
  262. X                else if (amode)     /* Apple macintosh text mode processing */
  263. X                    {
  264. X                    buff[bfctr] &= 0x7f;    /* nuke bit 8 */
  265. X                    if (c == 0)        /* skip nulls */
  266. X                        continue;
  267. X                    else if (c == CR)    /* translate CR to LF */
  268. X                        buff[bfctr] = LF;
  269. X                    else if (c == CTRLZ)    /* CP/M EOF char */
  270. X                        {  
  271. X                        recfin = TRUE;
  272. X                               continue;
  273. X                               }
  274. X                           if (!recfin)        /* don't increment if past EOF */
  275. X                        bfctr++;
  276. X                    }
  277. X                else            /* binary */
  278. X                    bfctr++;
  279. X
  280. X                 }    
  281. X
  282. X        /* go to sleep to save uneeded system calls while kernel
  283. X           is reading data from serial line; 
  284. X           fudge constant from 10000 to 9000 to avoid sleeping too long.
  285. X        */
  286. X        if (left && !TOOBUSY)
  287. X            napms( (left<SLEEPNUM ? left:SLEEPNUM) * 9000/ttyspeed);
  288. X
  289. X    }
  290. X
  291. X    if (CHECKLENGTH && fileread >= filelength)
  292. X        logitarg("File end from YMODEM length found in sector %s\n",
  293. X          sectdisp(recvsectcnt,bufsize,1));
  294. X    *checksum = chksm;
  295. X    *bufctr = bfctr;
  296. X    return(0);
  297. X}
  298. X
  299. X/* send a byte to data stream */
  300. X
  301. Xsendbyte(data)
  302. Xchar data;
  303. X    {
  304. X    if (DEBUG)
  305. X        fprintf(LOGFP, "DEBUG: sendbyte %02xh\n", data & 0xff);
  306. X
  307. X    if (write(1, &data, 1) != 1)      /* write the byte (assume it goes NOW; no flushing needed) */
  308. X        error ("Write error on stream", TRUE);
  309. X    return;
  310. X    }
  311. X
  312. X/* send a buffer to data stream */
  313. X
  314. Xwritebuf(buffer, nbytes)
  315. Xchar *buffer;
  316. Xint  nbytes;
  317. X    {
  318. X    if (DEBUG)
  319. X        fprintf(LOGFP, "DEBUG: writebuf (%d bytes)\n", nbytes);
  320. X
  321. X    if (write(1, buffer, nbytes) != nbytes)        /* write the buffer (assume no TIOCFLUSH needed) */
  322. X        error ("Write error on stream", TRUE);
  323. X    return;
  324. X    }
  325. X
  326. X/*
  327. X * "nap" for specified time -- VERY 4.2BSD specific
  328. X */
  329. X
  330. Xnapms (milliseconds)
  331. Xint    milliseconds;
  332. X{
  333. X    struct    timeval    timeout;
  334. X    int readfd;
  335. X
  336. X    if (milliseconds == 0)
  337. X        return;
  338. X    if (DEBUG)
  339. X        fprintf (LOGFP, "DEBUG: napping for %d ms\n", milliseconds);
  340. X    timeout.tv_sec = 0;
  341. X    timeout.tv_usec = milliseconds * 1000;
  342. X    readfd = 0;
  343. X
  344. X    (void) select(1, &readfd, (int *)0, (int *)0, &timeout);
  345. X}
  346. X
  347. X/* set and restore tty modes for XMODEM transfers */
  348. X/* These routines are 4.2/v7(?) specific */
  349. X
  350. Xstruct sgttyb ttys, ttysnew;    /* for stty terminal mode calls */
  351. Xstruct stat statbuf;        /* for terminal message on/off control */
  352. X
  353. Xint wason;            /* holds status of tty read write/modes */
  354. Xchar *tty;            /* current tty name */
  355. X
  356. X
  357. Xsetmodes()
  358. X    {
  359. X    char *ttyname();
  360. X
  361. X    int n;
  362. X
  363. X    extern onintr();
  364. X
  365. X    sleep(2);            /* let the output appear */
  366. X    if (ioctl(0,TIOCGETP,&ttys)<0)  /* get tty params [V7] */
  367. X        error("Can't get TTY Parameters", TRUE);
  368. X
  369. X    tty = ttyname(0);  /* identify current tty */
  370. X    
  371. X    ttysnew.sg_ispeed = ttys.sg_ispeed;    /* copy input speed */
  372. X    ttysnew.sg_ospeed = ttys.sg_ospeed;    /* copy input speed */
  373. X    ttysnew.sg_flags |= RAW;    /* set for RAW Mode */
  374. X    ttysnew.sg_flags &= ~ECHO;    /* set for no echoing */
  375. X    ttysnew.sg_flags &= ~TANDEM;    /* turn off flow control */
  376. X
  377. X    /* set new paramters */
  378. X    if (ioctl(0,TIOCSETP,&ttysnew) < 0)
  379. X        error("Can't set new TTY Parameters", TRUE);
  380. X
  381. X    /* Flush characters waiting for read or write */
  382. X    n = 0;
  383. X    if (ioctl(0,TIOCFLUSH,&n) < 0)
  384. X        error("Can't flush terminal queue", TRUE);
  385. X
  386. X    if (stat(tty, &statbuf) < 0)    /* get tty modes */ 
  387. X        {
  388. X        logit("Can't get your TTY Status\n");
  389. X        tlogit("Can't get your TTY Status\n");
  390. X        wason = FALSE;
  391. X        }
  392. X    else
  393. X        {
  394. X        if (statbuf.st_mode & 022)
  395. X            {
  396. X            if (chmod(tty, (int)statbuf.st_mode & ~022) < 0)
  397. X                {
  398. X                logit("Can't change TTY mode\n");
  399. X                tlogit("Can't change TTY mode\n");
  400. X                wason = FALSE;
  401. X                }
  402. X            else 
  403. X                wason = TRUE;
  404. X            }
  405. X        else 
  406. X            wason = FALSE;
  407. X        }
  408. X
  409. X    /* set up signal catcher to restore tty state if we are KILLed */
  410. X
  411. X    if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
  412. X        signal(SIGTERM, onintr);
  413. X    }
  414. X
  415. X/* restore normal tty modes */
  416. X
  417. Xrestoremodes(errcall)
  418. Xint errcall;
  419. X    {
  420. X    if (wason)
  421. X        if (chmod(tty, (int)statbuf.st_mode | 022) < 0)
  422. X            error("Can't change TTY mode", FALSE);
  423. X    if (ioctl(0,TIOCSETP,&ttys) < 0)
  424. X        { if (!errcall)
  425. X           error("RESET - Can't restore normal TTY Params", FALSE);
  426. X        else
  427. X             printf("RESET - Can't restore normal TTY Params\n");
  428. X        }
  429. X    if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
  430. X        signal(SIGTERM, SIG_DFL);
  431. X    return;
  432. X    }
  433. X
  434. X
  435. X
  436. X
  437. X/* signal catcher */
  438. Xonintr()
  439. X    {
  440. X    error("Kill signal; bailing out", TRUE);
  441. X    }
  442. X
  443. X/* create string with a timestamp for log file */
  444. X
  445. Xchar *stamptime()
  446. X{
  447. X    char *asctime();        /* stuff to get timestamp */
  448. X    struct tm *localtime(), *tp;
  449. X    struct timeval tv;
  450. X    struct timezone tz;
  451. X
  452. X    gettimeofday (&tv, &tz);        /* fill in timestamp */
  453. X    tp = localtime ((time_t *)&tv.tv_sec);
  454. X    return(asctime(tp));
  455. X}
  456. X
  457. X
  458. X
  459. X/* get tty speed for time estimates */
  460. X
  461. Xgetspeed()
  462. X    {
  463. X    static int speedtbl[] = {0, 50, 75, 110, 134, 150, 200, 300, 600, 
  464. X       1200, 1800, 2400, 4800, 9600, 19200, 0};
  465. X    if (ioctl(0,TIOCGETP,&ttys) < 0)    /* get tty structure */
  466. X        error("Can't get TTY parameters", FALSE);
  467. X
  468. X    if (ttys.sg_ispeed >= 0 && ttys.sg_ispeed <= 14)
  469. X        {
  470. X        ttyspeed = speedtbl[ttys.sg_ispeed];
  471. X        logitarg ("Line speed = %d bits per second\n", ttyspeed);
  472. X        }
  473. X    else
  474. X        {
  475. X        ttyspeed = 1200;
  476. X        logit ("Can't determine line speed; assuming 1200 bps\n");
  477. X        }
  478. X    }
  479. X
  480. X
  481. X/* turn off keyboard stop signal so stray ^X don't put us in background */
  482. X
  483. Xstopsig()
  484. X    {
  485. X    signal(SIGTSTP, SIG_IGN);
  486. X    }
  487. END_OF_FILE
  488.   if test 12356 -ne `wc -c <'getput.c'`; then
  489.     echo shar: \"'getput.c'\" unpacked with wrong size!
  490.   fi
  491.   # end of 'getput.c'
  492. fi
  493. if test -f 'getput.sysv.c' -a "${1}" != "-c" ; then 
  494.   echo shar: Will not clobber existing file \"'getput.sysv.c'\"
  495. else
  496.   echo shar: Extracting \"'getput.sysv.c'\" \(11185 characters\)
  497.   sed "s/^X//" >'getput.sysv.c' <<'END_OF_FILE'
  498. X/*
  499. X * Contains system routines to get and put bytes, change tty modes, etc
  500. X * Sys V version.  UNTESTED!!!!!!
  501. X */
  502. X
  503. X#include "xmodem.h"
  504. X
  505. X/*
  506. X *
  507. X *    Get a byte from the specified file.  Buffer the read so we don't
  508. X *    have to use a system call for each character.
  509. X *
  510. X */
  511. Xgetbyte(fildes, ch)                /* Buffered disk read */
  512. Xint fildes;
  513. Xchar *ch;
  514. X
  515. X    {
  516. X    static char buf[BUFSIZ];    /* Remember buffer */
  517. X    static char *bufp = buf;    /* Remember where we are in buffer */
  518. X    
  519. X    if (nbchr == 0)            /* Buffer exausted; read some more */
  520. X        {
  521. X        if ((nbchr = read(fildes, buf, BUFSIZ)) < 0)
  522. X            error("File Read Error", TRUE);
  523. X        bufp = buf;        /* Set pointer to start of array */
  524. X        }
  525. X    if (--nbchr >= 0)
  526. X        {
  527. X        *ch = *bufp++;
  528. X        return(0);
  529. X        }
  530. X    else
  531. X        {
  532. X        return(EOF);
  533. X        }
  534. X    }
  535. X
  536. X/* Count the number of newlines in a file so we know the REAL file size */
  537. X
  538. Xlong
  539. Xcountnl(fd)
  540. Xint fd;
  541. X{
  542. X    char buf[BUFSIZ];
  543. X    char *bufp;
  544. X    long nltot = 0;
  545. X    int numchar;
  546. X    long lseek();
  547. X
  548. X    while (numchar = read(fd, buf, BUFSIZ))        /* cycle through file */
  549. X        for (bufp=buf; numchar--; bufp++)
  550. X            if (*bufp == '\n')
  551. X                nltot++;
  552. X
  553. X    (void) lseek (fd, 0l, 0);            /* rewind file */
  554. X    if (DEBUG)
  555. X        fprintf(LOGFP, "DEBUG: countnl--%ld newlines counted\n", nltot);
  556. X    return (nltot);
  557. X}
  558. X
  559. X/*   CRC-16 constant array...
  560. X     from Usenet contribution by Mark G. Mendel, Network Systems Corp.
  561. X     (ihnp4!umn-cs!hyper!mark)
  562. X*/
  563. X
  564. X/* crctab as calculated by initcrctab() */
  565. Xunsigned short crctab[1<<B] = { 
  566. X    0x0000,  0x1021,  0x2042,  0x3063,  0x4084,  0x50a5,  0x60c6,  0x70e7,
  567. X    0x8108,  0x9129,  0xa14a,  0xb16b,  0xc18c,  0xd1ad,  0xe1ce,  0xf1ef,
  568. X    0x1231,  0x0210,  0x3273,  0x2252,  0x52b5,  0x4294,  0x72f7,  0x62d6,
  569. X    0x9339,  0x8318,  0xb37b,  0xa35a,  0xd3bd,  0xc39c,  0xf3ff,  0xe3de,
  570. X    0x2462,  0x3443,  0x0420,  0x1401,  0x64e6,  0x74c7,  0x44a4,  0x5485,
  571. X    0xa56a,  0xb54b,  0x8528,  0x9509,  0xe5ee,  0xf5cf,  0xc5ac,  0xd58d,
  572. X    0x3653,  0x2672,  0x1611,  0x0630,  0x76d7,  0x66f6,  0x5695,  0x46b4,
  573. X    0xb75b,  0xa77a,  0x9719,  0x8738,  0xf7df,  0xe7fe,  0xd79d,  0xc7bc,
  574. X    0x48c4,  0x58e5,  0x6886,  0x78a7,  0x0840,  0x1861,  0x2802,  0x3823,
  575. X    0xc9cc,  0xd9ed,  0xe98e,  0xf9af,  0x8948,  0x9969,  0xa90a,  0xb92b,
  576. X    0x5af5,  0x4ad4,  0x7ab7,  0x6a96,  0x1a71,  0x0a50,  0x3a33,  0x2a12,
  577. X    0xdbfd,  0xcbdc,  0xfbbf,  0xeb9e,  0x9b79,  0x8b58,  0xbb3b,  0xab1a,
  578. X    0x6ca6,  0x7c87,  0x4ce4,  0x5cc5,  0x2c22,  0x3c03,  0x0c60,  0x1c41,
  579. X    0xedae,  0xfd8f,  0xcdec,  0xddcd,  0xad2a,  0xbd0b,  0x8d68,  0x9d49,
  580. X    0x7e97,  0x6eb6,  0x5ed5,  0x4ef4,  0x3e13,  0x2e32,  0x1e51,  0x0e70,
  581. X    0xff9f,  0xefbe,  0xdfdd,  0xcffc,  0xbf1b,  0xaf3a,  0x9f59,  0x8f78,
  582. X    0x9188,  0x81a9,  0xb1ca,  0xa1eb,  0xd10c,  0xc12d,  0xf14e,  0xe16f,
  583. X    0x1080,  0x00a1,  0x30c2,  0x20e3,  0x5004,  0x4025,  0x7046,  0x6067,
  584. X    0x83b9,  0x9398,  0xa3fb,  0xb3da,  0xc33d,  0xd31c,  0xe37f,  0xf35e,
  585. X    0x02b1,  0x1290,  0x22f3,  0x32d2,  0x4235,  0x5214,  0x6277,  0x7256,
  586. X    0xb5ea,  0xa5cb,  0x95a8,  0x8589,  0xf56e,  0xe54f,  0xd52c,  0xc50d,
  587. X    0x34e2,  0x24c3,  0x14a0,  0x0481,  0x7466,  0x6447,  0x5424,  0x4405,
  588. X    0xa7db,  0xb7fa,  0x8799,  0x97b8,  0xe75f,  0xf77e,  0xc71d,  0xd73c,
  589. X    0x26d3,  0x36f2,  0x0691,  0x16b0,  0x6657,  0x7676,  0x4615,  0x5634,
  590. X    0xd94c,  0xc96d,  0xf90e,  0xe92f,  0x99c8,  0x89e9,  0xb98a,  0xa9ab,
  591. X    0x5844,  0x4865,  0x7806,  0x6827,  0x18c0,  0x08e1,  0x3882,  0x28a3,
  592. X    0xcb7d,  0xdb5c,  0xeb3f,  0xfb1e,  0x8bf9,  0x9bd8,  0xabbb,  0xbb9a,
  593. X    0x4a75,  0x5a54,  0x6a37,  0x7a16,  0x0af1,  0x1ad0,  0x2ab3,  0x3a92,
  594. X    0xfd2e,  0xed0f,  0xdd6c,  0xcd4d,  0xbdaa,  0xad8b,  0x9de8,  0x8dc9,
  595. X    0x7c26,  0x6c07,  0x5c64,  0x4c45,  0x3ca2,  0x2c83,  0x1ce0,  0x0cc1,
  596. X    0xef1f,  0xff3e,  0xcf5d,  0xdf7c,  0xaf9b,  0xbfba,  0x8fd9,  0x9ff8,
  597. X    0x6e17,  0x7e36,  0x4e55,  0x5e74,  0x2e93,  0x3eb2,  0x0ed1,  0x1ef0
  598. X    };
  599. X
  600. X/* get a byte from data stream -- timeout if "seconds" elapses */
  601. X
  602. Xint timedout;
  603. Xint
  604. Xreadbyte(seconds)
  605. Xint seconds;
  606. X{
  607. X    int force_it();
  608. X    char c;
  609. X    signal(SIGALRM, force_it);
  610. X
  611. X    timedout = 0;
  612. X    alarm(seconds);
  613. X    read(0, &c, 1);
  614. X    alarm(0);
  615. X    if (timedout)
  616. X        {
  617. X        if (DEBUG)
  618. X            fprintf(LOGFP, "DEBUG: readbyte TIMEOUT\n");
  619. X        return(TIMEOUT);
  620. X        }
  621. X    if (DEBUG)
  622. X        fprintf(LOGFP, "DEBUG: readbyte %02xh\n", c & 0xff);
  623. X    return(c & 0xff);
  624. X}
  625. X
  626. Xint
  627. Xforce_it()
  628. X{
  629. X    timedout++;
  630. X    return;
  631. X}
  632. X
  633. X
  634. X/* flush input stream */
  635. X
  636. Xflushin()
  637. X    {
  638. X/* No good way to do this without select */
  639. X/* Perhaps....but we waste 1 second with every call!
  640. X    while (readbyte(1) != TIMEOUT)
  641. X        ;
  642. X*/
  643. X    }
  644. X
  645. X/* 
  646. X get a buffer (length bufsize) from data stream -- timeout if "seconds" elapses.
  647. X Read bunches of characters to save system overhead;
  648. X Further process data while kernel is reading stream (calculating "checksum").
  649. X Try to nap long enough so kernel collects 100 characters or so until we wake up
  650. X unless TOOBUSY is set.
  651. X*/
  652. X
  653. X
  654. Xint
  655. Xreadbuf(bufsize, seconds, tmode, amode, recvsectcnt, checksum, bufctr)
  656. X
  657. Xint bufsize,    /* number of chars to be read */
  658. Xseconds,     /* timeout period for each read */
  659. Xtmode,         /* transmission mode: TRUE if text */
  660. Xamode,         /* transmission mode: TRUE if apple macintosh */
  661. X*checksum,     /* pointer to checksum value */
  662. X*bufctr;    /* length of actual data string in buffer */
  663. Xlong recvsectcnt;    /* running sector count (128 byte sectors) */
  664. X
  665. X{
  666. X    int force_it();
  667. X    int numread;        /* number of chars read */
  668. X    int left;        /* number of chars left to read */
  669. X    int recfin = 0;        /* flag that EOF read */
  670. X    char inbuf[BBUFSIZ];    /* buffer for incoming packet */
  671. X    register unsigned char c;    /* character being processed */
  672. X    register unsigned short chksm;    /* working copy of checksum */
  673. X    register int bfctr;    /* working copy of bufctr */
  674. X    int j;            /* loop index */
  675. X    char *sectdisp();
  676. X
  677. X    signal(SIGALRM, force_it);
  678. X    chksm = 0;
  679. X    bfctr = 0;
  680. X
  681. X    for (left = bufsize; left > 0;) {
  682. X
  683. X        /* read however many chars are waiting */
  684. X        timedout = 0;
  685. X        alarm(seconds);
  686. X        numread = read(0, inbuf, left);
  687. X        alarm(0);
  688. X        if (timedout)
  689. X            return(TIMEOUT);
  690. X        left -= numread;
  691. X
  692. X        if (DEBUG)
  693. X            fprintf(LOGFP, "DEBUG: readbuf--read %d characters\n", numread);
  694. X
  695. X        /* now process part of packet we just read */
  696. X
  697. X        for (j =  0; j < numread; j++) 
  698. X            {  
  699. X                buff[bfctr] = c = inbuf[j] & 0xff;
  700. X                fileread++;
  701. X
  702. X                if (CRCMODE)  /* CRC */
  703. X                    chksm = (chksm<<B) ^ crctab[(chksm>>(W-B)) ^ c];
  704. X
  705. X                else        /* checksum */
  706. X                           chksm = ((chksm+c) & 0xff);
  707. X
  708. X                if (CHECKLENGTH && fileread > filelength)    /* past EOF ? */
  709. X                    continue;
  710. X
  711. X                if (tmode)         /* text mode processing */
  712. X                    {
  713. X                    buff[bfctr] &= 0x7f;    /* nuke bit 8 */
  714. X                    if (c == CR || c == 0)    /* skip CRs and nulls */
  715. X                        continue;
  716. X                    else if (c == CTRLZ)    /* CP/M EOF char */
  717. X                        {  
  718. X                        recfin = TRUE;
  719. X                               continue;
  720. X                               }
  721. X                           else if (!recfin)    /* don't increment if past EOF */
  722. X                        bfctr++;
  723. X                    }
  724. X                else if (amode)     /* Apple macintosh text mode processing */
  725. X                    {
  726. X                    buff[bfctr] &= 0x7f;    /* nuke bit 8 */
  727. X                    if (c == 0)        /* skip nulls */
  728. X                        continue;
  729. X                    else if (c == CR)    /* translate CR to LF */
  730. X                        buff[bfctr] = LF;
  731. X                    else if (c == CTRLZ)    /* CP/M EOF char */
  732. X                        {  
  733. X                        recfin = TRUE;
  734. X                               continue;
  735. X                               }
  736. X                           if (!recfin)    /* don't increment if past EOF */
  737. X                        bfctr++;
  738. X                    }
  739. X                else            /* binary */
  740. X                    bfctr++;
  741. X
  742. X                 }    
  743. X
  744. X        /* go to sleep to save uneeded system calls while kernel
  745. X           is reading data from serial line, fudge constant from 10 to
  746. X           9 to avoid sleeping too long
  747. X        */
  748. X        if (left && !TOOBUSY)
  749. X            sleep ((left<SLEEPNUM ? left:SLEEPNUM) * 9/ttyspeed);
  750. X    }
  751. X
  752. X    if (CHECKLENGTH && fileread >= filelength)
  753. X        logitarg("File end from YMODEM length found in sector %s\n",
  754. X          sectdisp(recvsectcnt,bufsize,1));
  755. X    *checksum = chksm;
  756. X    *bufctr = bfctr;
  757. X    return(0);
  758. X}
  759. X
  760. X/* send a byte to data stream */
  761. X
  762. Xsendbyte(data)
  763. Xchar data;
  764. X    {
  765. X    if (DEBUG)
  766. X        fprintf(LOGFP, "DEBUG: sendbyte %02xh\n", data & 0xff);
  767. X
  768. X    if (write(1, &data, 1) != 1)      /* write the byte (assume it goes NOW; no flushing needed) */
  769. X        error ("Write error on stream", TRUE);
  770. X    return;
  771. X    }
  772. X
  773. X/* send a buffer to data stream */
  774. X
  775. Xwritebuf(buffer, nbytes)
  776. Xchar *buffer;
  777. Xint  nbytes;
  778. X    {
  779. X    if (DEBUG)
  780. X        fprintf(LOGFP, "DEBUG: writebuf (%d bytes)\n", nbytes);
  781. X
  782. X    if (write(1, buffer, nbytes) != nbytes)        /* write the buffer (assume no TIOCFLUSH needed) */
  783. X        error ("Write error on stream", TRUE);
  784. X    return;
  785. X    }
  786. X
  787. X/* set and restore tty modes for XMODEM transfers */
  788. X
  789. Xstruct termio ttys;
  790. Xstruct stat statbuf;        /* for terminal message on/off control */
  791. X
  792. Xint wason;            /* holds status of tty read write/modes */
  793. Xchar *tty;            /* current tty name */
  794. X
  795. X
  796. Xsetmodes()
  797. X    {
  798. X    char *ttyname();
  799. X    struct termio ttysnew;
  800. X
  801. X    extern onintr();
  802. X
  803. X    sleep(2);            /* let the output appear */
  804. X    if (ioctl(0,TCGETA,&ttys)<0)  /* get tty params */
  805. X        error("Can't get TTY Parameters", TRUE);
  806. X
  807. X    tty = ttyname(0);  /* identify current tty */
  808. X    
  809. X    if (ioctl(0,TCGETA,&ttysnew)<0)  /* get tty params */
  810. X        error("Can't get TTY Parameters", TRUE);
  811. X    ttysnew.c_cc[4] = 1;        /* VMIN */
  812. X    ttysnew.c_cc[5] = 0;        /* VTIME */
  813. X    ttysnew.c_iflag = 0;
  814. X    ttysnew.c_oflag = 0;
  815. X    ttysnew.c_lflag = 0;
  816. X    ttysnew.c_cflag &= ~CSIZE;
  817. X    ttysnew.c_cflag |= CS8;
  818. X    ttysnew.c_cflag &= ~PARENB;
  819. X    if (ioctl(0,TCSETA,&ttysnew)<0)  /* set new paramters */
  820. X        error("Can't set new TTY Parameters", TRUE);
  821. X
  822. X    if (stat(tty, &statbuf) < 0)    /* get tty modes */ 
  823. X        {
  824. X        logit("Can't get your TTY Status\n");
  825. X        tlogit("Can't get your TTY Status\n");
  826. X        wason = FALSE;
  827. X        }
  828. X    else
  829. X        {
  830. X        if (statbuf.st_mode & 022)
  831. X            {
  832. X            if (chmod(tty, (int)statbuf.st_mode & ~022) < 0)
  833. X                {
  834. X                logit("Can't change TTY mode\n");
  835. X                tlogit("Can't change TTY mode\n");
  836. X                wason = FALSE;
  837. X                }
  838. X            else 
  839. X                wason = TRUE;
  840. X            }
  841. X        else 
  842. X            wason = FALSE;
  843. X        }
  844. X
  845. X
  846. X    /* set up signal catcher to restore tty state if we are KILLed */
  847. X
  848. X    if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
  849. X        signal(SIGTERM, onintr);
  850. X    }
  851. X
  852. X/* restore normal tty modes */
  853. X
  854. Xrestoremodes(errcall)
  855. Xint errcall;
  856. X    {
  857. X    if (wason)
  858. X        if (chmod(tty, (int)statbuf.st_mode | 022) < 0)
  859. X            error("Can't change TTY mode", FALSE);
  860. X    if (ioctl(0,TCSETA,&ttys) < 0)
  861. X        { if (!errcall)
  862. X           error("RESET - Can't restore normal TTY Params", FALSE);
  863. X        else
  864. X             printf("RESET - Can't restore normal TTY Params\n");
  865. X        }
  866. X    if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
  867. X        signal(SIGTERM, SIG_DFL);
  868. X    return;
  869. X    }
  870. X
  871. X
  872. X
  873. X
  874. X/* signal catcher */
  875. Xonintr()
  876. X    {
  877. X    error("Kill signal; bailing out", TRUE);
  878. X    }
  879. X
  880. X/* create string with a timestamp for log file */
  881. X
  882. Xchar *stamptime()
  883. X{
  884. X    char *asctime();        /* stuff to get timestamp */
  885. X    struct tm *localtime(), *tp;
  886. X    long now;
  887. X
  888. X    time(&now);
  889. X    tp = localtime(&now);
  890. X    return(asctime(tp));
  891. X}
  892. X
  893. X
  894. X
  895. X/* get tty speed for time estimates */
  896. X
  897. Xgetspeed()
  898. X    {
  899. X    static int speedtbl[] = {0, 50, 75, 110, 134, 150, 200, 300, 600,
  900. X    1200, 1800, 2400, 4800, 9600, 19200, 0};
  901. X    struct termio ttystemp;
  902. X
  903. X    if (ioctl(0,TCGETA,&ttystemp) < 0)    /* get tty structure */
  904. X        error("Can't get TTY parameters", FALSE);
  905. X    if ((ttystemp.c_cflag & 017) >= 0 && (ttystemp.c_cflag & 017) <= 14)
  906. X        {
  907. X        ttyspeed = speedtbl[ttystemp.c_cflag & 017];
  908. X        logitarg ("Line speed = %d bits per second\n", ttyspeed);
  909. X        }
  910. X    else
  911. X        {
  912. X        ttyspeed = 1200;
  913. X        logit ("Can't determine line speed; assuming 1200 bps\n");
  914. X        }
  915. X    }
  916. X
  917. X
  918. X/* turn off keyboard stop signal so stray ^X don't put us in background */
  919. X
  920. Xstopsig()
  921. X    {
  922. X    }
  923. END_OF_FILE
  924.   if test 11185 -ne `wc -c <'getput.sysv.c'`; then
  925.     echo shar: \"'getput.sysv.c'\" unpacked with wrong size!
  926.   fi
  927.   # end of 'getput.sysv.c'
  928. fi
  929. if test -f 'send.c' -a "${1}" != "-c" ; then 
  930.   echo shar: Will not clobber existing file \"'send.c'\"
  931. else
  932.   echo shar: Extracting \"'send.c'\" \(12219 characters\)
  933.   sed "s/^X//" >'send.c' <<'END_OF_FILE'
  934. X/**  send a file  **/
  935. X
  936. X/*
  937. X * Operation of this routine depends on on MDM7BAT and YMDMBAT flags.
  938. X *
  939. X * If "name" is NULL; close out the BATCH send.
  940. X */
  941. X
  942. X#include "xmodem.h"
  943. X
  944. Xsfile(name)
  945. Xchar *name;
  946. X    {
  947. X
  948. X    char *sectdisp();
  949. X    time_t time();
  950. X    char *strcpy();
  951. X    char *unix_cpm();
  952. X    char *cpmify();
  953. X    long countnl();
  954. X
  955. X    extern unsigned short crctab[1<<B];    /* CRC-16 constant values, see getput.c */
  956. X
  957. X    register int bufctr,         /* array index for data buffer */
  958. X    sectnum;            /* packet number for packet header */
  959. X
  960. X    register unsigned short checksum;     /* checksum/crc */
  961. X
  962. X    char blockbuf[BBUFSIZ+6];    /* holds packet as it is constructed */
  963. X
  964. X    struct stat filestatbuf;    /* file status info */
  965. X
  966. X    int fd,         /* file descriptor for file being transmitted */
  967. X    attempts,        /* number of attempts made to transmit a packet */
  968. X    nlflag,         /* flag that we have to send a LF in next packet */
  969. X    sendfin,         /* flag that we are sending the last packet */
  970. X    closeout,        /* flag that we are closing out batch send */
  971. X    startup,        /* flag that we are starting batch send */
  972. X    tmode,            /* TRUE for text mode */
  973. X    amode,            /* TRUE for apple mode */
  974. X    filepack,        /* TRUE when sending first packet */
  975. X    buf1024,        /* TRUE when sending 1K packets */
  976. X    bbufcnt,        /* array index for packet */
  977. X    firstchar,        /* first character in protocol transaction */
  978. X    bufsize,        /* packet size (128 or 1024) */
  979. X    sendresp;          /* response char to sent block received from remote*/
  980. X    long sentsect;        /* count of 128 byte sectors actually sent */
  981. X    long expsect;        /* count of 128 byte sectors expected to be sent */
  982. X    time_t start;        /* starting time of transfer */
  983. X    char c;
  984. X
  985. X    nbchr = 0;  /* clear buffered read char count */
  986. X
  987. X    CRCMODE = FALSE;    /* Receiver determines use of crc or checksum */
  988. X    YMODEMG = FALSE;    /* Receiver determines use YMODEM-G */
  989. X
  990. X    buf1024 = LONGPACK;    /* set packet size flag to command line switch */
  991. X
  992. X    closeout = FALSE; startup = TRUE; filepack = FALSE;    /* indicate state of batch transfer */
  993. X
  994. X    tmode = (XMITTYPE == 't') ? TRUE : FALSE;    /* set text mode */
  995. X    amode = (XMITTYPE == 'a') ? TRUE : FALSE;    /* set apple mode */
  996. X
  997. X    /* Check on NULL file name */
  998. X    if (strcmp(name,"") == 0)
  999. X        {
  1000. X        if (BATCH)
  1001. X            closeout = TRUE;
  1002. X        else
  1003. X            {
  1004. X            sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
  1005. X            error("NULL file name in send", TRUE);
  1006. X            }
  1007. X        }
  1008. X
  1009. X    if (!closeout)        /* Are we closing down batch? */
  1010. X        {            /* no; let's send a file */
  1011. X        logit("----\nXMODEM Send Function\n");
  1012. X        tlogit("----\nXMODEM Send Function\n");
  1013. X
  1014. X        if ((fd = open(name, 0)) < 0)    
  1015. X            {  
  1016. X            sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
  1017. X                    error("Can't open file for send", TRUE);
  1018. X            }
  1019. X    
  1020. X        stat(name, &filestatbuf);  /* get file status bytes */
  1021. X        if (tmode)           /* count up NLs */
  1022. X            filestatbuf.st_size += countnl(fd);
  1023. X        expsect = (filestatbuf.st_size/128) + 1;
  1024. X    
  1025. X        if (LOGFLAG)
  1026. X            {   
  1027. X                fprintf(LOGFP, "File Name: %s\n", name);
  1028. X              fprintf(LOGFP,"File Size %ldK, %ld Records, %ld Bytes\n",
  1029. X                (filestatbuf.st_size/1024)+1, expsect, filestatbuf.st_size);
  1030. X            projtime(expsect, LOGFP);
  1031. X            }
  1032. X        if (TIPFLAG)
  1033. X            {
  1034. X                fprintf(stderr, "File Name: %s\n", name);
  1035. X              fprintf(stderr,"File Size %ldK, %ld Records, %ld Bytes\n",
  1036. X              (filestatbuf.st_size/1024)+1, expsect, filestatbuf.st_size);
  1037. X            projtime(expsect, stderr);
  1038. X            }
  1039. X        }
  1040. X    else
  1041. X        {
  1042. X        logit("----\nXMODEM Send Function\n");
  1043. X        logit("Closing down Batch Transmission\n");
  1044. X        tlogit("Closing down Batch Transmission\n");
  1045. X        }
  1046. X
  1047. X
  1048. X    bufsize = buf1024 ? 1024 : 128;        /* set sector size */
  1049. X    if (buf1024 && !closeout)
  1050. X        {
  1051. X        logit("1K packet mode chosen on command line\n");
  1052. X        tlogit("1K packet mode chosen on command line\n");
  1053. X        }
  1054. X
  1055. X        sendfin = nlflag = FALSE;
  1056. X      attempts = 0;
  1057. X
  1058. X    /* wait for and read startup character */
  1059. Xrestart:
  1060. X    do
  1061. X        {
  1062. X        while (((firstchar=readbyte(1)) != NAK) && (firstchar != CRCCHR) && (firstchar != GCHR) && (firstchar != CAN))
  1063. X            if (++attempts > NAKMAX)
  1064. X                {
  1065. X                if (MDM7BAT && startup)
  1066. X                    {
  1067. X                    sendbyte(ACK); sendbyte(EOT);
  1068. X                    }
  1069. X                error("Remote System Not Responding", TRUE);
  1070. X                }
  1071. X
  1072. X        if ((firstchar & 0x7f) == CAN)
  1073. X            if (readbyte(3) == CAN)
  1074. X                error("Send Canceled by CAN-CAN",TRUE);
  1075. X
  1076. X        if (firstchar == GCHR)
  1077. X            {
  1078. X            CRCMODE = TRUE;
  1079. X            YMODEMG = TRUE;
  1080. X            CANCAN = TRUE;
  1081. X            if (!closeout)
  1082. X                {
  1083. X                logit("Receiver invoked YMODEM-G and CRC modes\n");
  1084. X                tlogit("Receiver invoked YMODEM-G and CRC modes\n");
  1085. X                }
  1086. X            }
  1087. X        if (firstchar == CRCCHR)
  1088. X            {
  1089. X            CRCMODE = TRUE;
  1090. X            if (!closeout)
  1091. X                {
  1092. X                logit("Receiver invoked CRC mode\n");
  1093. X                tlogit("Receiver invoked CRC mode\n");
  1094. X                }
  1095. X            if (readbyte(1) == KCHR)
  1096. X                {
  1097. X                buf1024 = TRUE;
  1098. X                logit("Receiver invoked 1K packet mode\n");
  1099. X                tlogit("Receiver invoked 1K packet mode\n");
  1100. X                }
  1101. X            }
  1102. X        }
  1103. X    while (firstchar != NAK && firstchar != CRCCHR && firstchar != GCHR);
  1104. X
  1105. X    if (MDM7BAT && closeout)    /* close out MODEM7 batch */
  1106. X        {
  1107. X        sendbyte(ACK); sendbyte (EOT);
  1108. X        flushin(); readbyte(2);     /* flush junk */
  1109. X        return;
  1110. X        }
  1111. X
  1112. X    if (MDM7BAT && startup)        /* send MODEM7 file name */
  1113. X        {
  1114. X        if (send_name(unix_cpm(name)) == -1)
  1115. X            {
  1116. X            attempts = 0;
  1117. X            goto restart;
  1118. X            }
  1119. X        startup = FALSE;
  1120. X        attempts = 0;
  1121. X        goto restart;
  1122. X        }
  1123. X
  1124. X    sectnum = 1;
  1125. X
  1126. X    if (YMDMBAT)    /* Fudge for YMODEM transfer (to send name packet) */
  1127. X        {
  1128. X        sectnum = 0;
  1129. X        bufsize = 128;
  1130. X        filepack = TRUE;
  1131. X        }
  1132. X
  1133. X    attempts = sentsect = 0;
  1134. X    start = time((time_t *) 0);
  1135. X
  1136. X        do             /* outer packet building/sending loop; loop till whole file is sent */
  1137. X        {   
  1138. X
  1139. X        if (closeout && YMDMBAT && sectnum == 1)    /* close out YMODEM */
  1140. X            return;
  1141. X
  1142. X        if (YMDMBAT && sectnum == 1)            /* get set to send YMODEM data packets */
  1143. X            {
  1144. X            bufsize = buf1024 ? 1024 : 128;
  1145. X
  1146. X            do        /* establish handshaking again */
  1147. X                {
  1148. X                while (((firstchar=readbyte(2)) != CRCCHR) && (firstchar != GCHR) && (firstchar != NAK) && (firstchar != CAN))
  1149. X                    if (++attempts > ERRORMAX)
  1150. X                        error("YMODEM protocol botch, C or G expected", TRUE);
  1151. X                if ((firstchar&0x7f) == CAN)
  1152. X                    if (readbyte(3) == CAN)
  1153. X                        error("Send Canceled by CAN-CAN", TRUE);
  1154. X                }
  1155. X            while ((firstchar != CRCCHR) &&  (firstchar != GCHR) && (firstchar != NAK));
  1156. X
  1157. X            attempts = 0;
  1158. X            }
  1159. X
  1160. X        if ((bufsize == 1024) && (attempts > KSWMAX))
  1161. X            {
  1162. X            logit("Reducing packet size to 128 due to excessive errors\n");
  1163. X            tlogit("Reducing packet size to 128 due to excessive errors\n");
  1164. X            bufsize = 128;
  1165. X            }
  1166. X
  1167. X        if ((bufsize == 1024) && ((expsect - sentsect) < 8))
  1168. X            {
  1169. X            logit("Reducing packet size to 128 for tail end of file\n");
  1170. X            tlogit("Reducing packet size to 128 for tail end of file\n");
  1171. X            bufsize = 128;
  1172. X            }
  1173. X
  1174. X        if (sectnum > 0)    /* data packet */
  1175. X            {
  1176. X            for (bufctr=0; bufctr < bufsize;)
  1177. X                    {
  1178. X                if (nlflag)
  1179. X                            {  
  1180. X                    buff[bufctr++] = LF;  /* leftover newline */
  1181. X                               nlflag = FALSE;
  1182. X                        }
  1183. X                if (getbyte(fd, &c) == EOF)
  1184. X                    { 
  1185. X                    sendfin = TRUE;  /* this is the last sector */
  1186. X                       if (!bufctr)  /* if EOF on sector boundary */
  1187. X                              break;  /* avoid sending extra sector */
  1188. X                          buff[bufctr++] = CTRLZ;  /* pad with Ctrl-Z for CP/M EOF (even do for binary files) */
  1189. X                       continue;
  1190. X                          }
  1191. X    
  1192. X                if (tmode && c == LF)  /* text mode & Unix newline? */
  1193. X                        {
  1194. X                    buff[bufctr++] = CR;  /* insert carriage return */
  1195. X                         if (bufctr < bufsize)
  1196. X                                buff[bufctr++] = LF;  /* insert LF */
  1197. X                           else
  1198. X                            nlflag = TRUE;  /* insert on next sector */
  1199. X                       }    
  1200. X                else if (amode && c == LF)   /* Apple mode & Unix newline? */
  1201. X                    buff[bufctr++] = CR; /* substitute CR */
  1202. X                else
  1203. X                    buff[bufctr++] = c;  /* copy the char without change */
  1204. X                    }
  1205. X
  1206. X                if (!bufctr)  /* if EOF on sector boundary */
  1207. X                          break;  /* avoid sending empty sector */
  1208. X            }    
  1209. X
  1210. X        else        /* YMODEM filename packet */
  1211. X            {
  1212. X            for (bufctr=0; bufctr<1024; bufctr++)  /* zero packet */
  1213. X                buff[bufctr]=0;
  1214. X            if (!closeout)
  1215. X                {
  1216. X                strcpy((char *)buff, cpmify(name));
  1217. X                
  1218. X                    /* put in file name, length, mode, */
  1219. X                    /* dummy SN, files, bytes remaining and file type */
  1220. X                    {
  1221. X                    register char *p;
  1222. X                    p = (char *)buff + strlen(buff) + 1;
  1223. X                    sprintf(p, "%lu %lo %o 0 %d %ld 0", filestatbuf.st_size, 
  1224. X                      filestatbuf.st_mtime, filestatbuf.st_mode,
  1225. X                      yfilesleft, ytotleft);
  1226. X                    if (DEBUG)
  1227. X                        fprintf(LOGFP, "DEBUG: YMODEM header information: %s %s\n", buff, p);
  1228. X                    }
  1229. X                if (buff[125])        /* need to have long packet? */
  1230. X                    {
  1231. X                    bufsize = 1024;
  1232. X                    if (DEBUG)
  1233. X                        fprintf(LOGFP, "DEBUG: YMODEM header sent in 1024 byte packet\n");
  1234. X                    }
  1235. X                buff[bufsize-2]    = (expsect & 0xff);        /* put in KMD kludge information */
  1236. X                buff[bufsize-1] = ((expsect >> 8) & 0xff);
  1237. X
  1238. X                /* update totals */
  1239. X                ytotleft -= filestatbuf.st_size;
  1240. X                if (--yfilesleft <= 0)
  1241. X                    ytotleft = 0;
  1242. X                if (ytotleft < 0)
  1243. X                    ytotleft = 0;
  1244. X                }
  1245. X            }
  1246. X
  1247. X        bbufcnt = 0;        /* start building block to be sent */
  1248. X        blockbuf[bbufcnt++] = (bufsize == 1024) ? STX : SOH;    /* start of packet char */
  1249. X        blockbuf[bbufcnt++] = sectnum;        /* current sector # */
  1250. X        blockbuf[bbufcnt++] = ~sectnum;   /* and its complement */
  1251. X
  1252. X                   checksum = 0;  /* initialize checksum */
  1253. X                   for (bufctr=0; bufctr < bufsize; bufctr++)
  1254. X                   {
  1255. X            blockbuf[bbufcnt++] = buff[bufctr];
  1256. X
  1257. X            if (CRCMODE)
  1258. X                checksum = (checksum<<B) ^ crctab[(checksum>>(W-B)) ^ buff[bufctr]];
  1259. X
  1260. X            else
  1261. X                           checksum = ((checksum+buff[bufctr]) & 0xff);
  1262. X                 }
  1263. X
  1264. X        if (CRCMODE)        /* put in CRC */
  1265. X            {
  1266. X            checksum &= 0xffff;
  1267. X            blockbuf[bbufcnt++] = ((checksum >> 8) & 0xff);
  1268. X            blockbuf[bbufcnt++] = (checksum & 0xff);
  1269. X            }
  1270. X        else            /* put in checksum */
  1271. X            blockbuf[bbufcnt++] = checksum;
  1272. X
  1273. X                attempts = 0;
  1274. X    
  1275. X                do                /* inner packet loop */
  1276. X                    {
  1277. X
  1278. X            writebuf(blockbuf, bbufcnt);    /* write the block */
  1279. X            if (!YMODEMG)
  1280. X                flushin();              /* purge anything in input queue */
  1281. X
  1282. X            if (DEBUG)
  1283. X                fprintf (LOGFP, "DEBUG: %d byte Packet %02xh (%02xh) sent, checksum %02xh %02xh\n", 
  1284. X                bbufcnt, blockbuf[1]&0xff, blockbuf[2]&0xff, blockbuf[bufsize+3]&0xff, blockbuf[bufsize+4]&0xff);
  1285. X
  1286. X                    attempts++;
  1287. X            sendresp = (YMODEMG) ? ACK : readbyte(10);    /* get response from remote  (or fake it for YMODEM-G) */
  1288. X
  1289. X            if (sendresp != ACK)
  1290. X                   {
  1291. X                if (sendresp == TIMEOUT)
  1292. X                    {
  1293. X                       logitarg("Timeout on sector %s\n",sectdisp(sentsect,bufsize,1));
  1294. X                       tlogitarg("Timeout on sector %s\n",sectdisp(sentsect,bufsize,1));
  1295. X                    }
  1296. X                if (sendresp == CAN)
  1297. X                    {
  1298. X                    if (CANCAN)
  1299. X                        {
  1300. X                        if (readbyte(3) == CAN)
  1301. X                            error("Send Canceled by CAN-CAN",TRUE);
  1302. X                        }
  1303. X                    else
  1304. X                        {
  1305. X                       logitarg("ignored CAN on sector %s\n",sectdisp(sentsect,bufsize,1));
  1306. X                       tlogitarg("ignored CAN on sector %s\n",sectdisp(sentsect,bufsize,1));
  1307. X                        }
  1308. X                    }
  1309. X                else if (sendresp == NAK)
  1310. X                    {
  1311. X                       logitarg("NAK on sector %s\n",sectdisp(sentsect,bufsize,1));
  1312. X                       tlogitarg("NAK on sector %s\n",sectdisp(sentsect,bufsize,1));
  1313. X                    }
  1314. X                else
  1315. X                    {
  1316. X                       logitarg("Non-ACK on sector %s\n",sectdisp(sentsect,bufsize,1));
  1317. X                       tlogitarg("Non-ACK on sector %s\n",sectdisp(sentsect,bufsize,1));
  1318. X                    }
  1319. X                   }
  1320. X                    }
  1321. X            while((sendresp != ACK) && (attempts < ERRORMAX));    /* close of inner loop */
  1322. X
  1323. X               sectnum++;  /* increment to next sector number */
  1324. X        if (!filepack)
  1325. X            sentsect += (bufsize == 128) ? 1 : 8;
  1326. X        filepack = FALSE;
  1327. X        if (TIPFLAG && sentsect % 32 == 0)
  1328. X            tlogitarg("Sector %s sent\n", sectdisp(sentsect,bufsize,0));
  1329. X            }
  1330. X        while (!sendfin && ( attempts < ERRORMAX));    /* end of outer loop */
  1331. X
  1332. X    if (attempts >= ERRORMAX)
  1333. X        {
  1334. X        sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); sendbyte(CAN);
  1335. X        error ("Too many errors in transmission", TRUE);
  1336. X        }
  1337. X
  1338. X        sendbyte(EOT);  /* send 1st EOT to close down transfer */
  1339. X        attempts = 0;
  1340. X    
  1341. X        while ((readbyte(15) != ACK) && (attempts++ < EOTMAX))     /* wait for ACK of EOT */
  1342. X        {
  1343. X        if (attempts > 1)
  1344. X            {
  1345. X            logitarg("EOT not ACKed, try %d\n", attempts);
  1346. X            tlogitarg("EOT not ACKed, try %d\n", attempts);
  1347. X            }
  1348. X           sendbyte(EOT);
  1349. X        }
  1350. X
  1351. X        if (attempts >= RETRYMAX)
  1352. X           error("Remote System Not Responding on Completion", TRUE);
  1353. X
  1354. X        close(fd);
  1355. X
  1356. X        logit("Send Complete\n");
  1357. X        tlogit("Send Complete\n");
  1358. X    if (LOGFLAG)
  1359. X        prtime(sentsect, time((time_t *) 0) - start, LOGFP);
  1360. X    if (TIPFLAG)
  1361. X        prtime(sentsect, time((time_t *) 0) - start, stderr);
  1362. X    }
  1363. END_OF_FILE
  1364.   if test 12219 -ne `wc -c <'send.c'`; then
  1365.     echo shar: \"'send.c'\" unpacked with wrong size!
  1366.   fi
  1367.   # end of 'send.c'
  1368. fi
  1369. if test -f 'update.doc' -a "${1}" != "-c" ; then 
  1370.   echo shar: Will not clobber existing file \"'update.doc'\"
  1371. else
  1372.   echo shar: Extracting \"'update.doc'\" \(12797 characters\)
  1373.   sed "s/^X//" >'update.doc' <<'END_OF_FILE'
  1374. XChanges leading to version 3.3
  1375. X
  1376. X1) "Better" handshaking for MODEM7 batch transfers (5/19/87).
  1377. X
  1378. X2) If reception of a file is aborted due to errors, delete incomplete file
  1379. X(5/19/87).
  1380. X
  1381. X3) If an "impossible" tty speed is detected, assume 1200 bps (5/19/87).
  1382. X
  1383. X4) Disallow CAN-CAN abort during file send or receive except at beginning of
  1384. Xfile transfer (during batch transfers, CAN-CAN abort is allowed at beginning
  1385. Xof each file transfer) (5/19/87).
  1386. X
  1387. X5) Uncouple total allowed errors during the reception of a single packet 
  1388. X(ERRORMAX, now made 10) and errors allowed when starting transfer (STERRORMAX, 
  1389. Xset to 10) (5/19/87).
  1390. X
  1391. X6) Fix some bugs when receiving an empty file and when a phase error occurs
  1392. Xduring a file reception (5/19/87).
  1393. X
  1394. X7) Portability fix in prtime and projtime; they also handle pathological
  1395. Xcases better (5/19/87).
  1396. X
  1397. X8) During file reception an EOT is not believed unless it is sent again in
  1398. Xresponse to a NAK (5/25/87).
  1399. X
  1400. X9) Modified cpm_unix and unixify so a filename without an extension will not
  1401. Xhave a trailing dot in its filename after being received in a MODEM7 or
  1402. XYMODEM batch transfer (5/25/87).
  1403. X
  1404. X10) Allowable errors during transmission of a single packet now set to
  1405. XERRORMAX (5/27/87).
  1406. X
  1407. X11) When transferring a binary file, the YMODEM file length field is filled
  1408. Xin on transmit and (if present) used to truncate the file on reception.
  1409. XA new truncate function (truncfile) added to getput.c to do the deed (5/28/87).
  1410. XThe file mode field is also set but is ignored on file reception.
  1411. X
  1412. X12) In a batch receive (xmodem -rt), program can be forced into checksum mode
  1413. Xby specifying the "M" flag indicating a MODEM7 transfer (5/30/87).
  1414. X
  1415. X13) Changed the "B" option to "M" to indicate MODEM7 batch.  Made all option
  1416. Xflags case insensitive.  Command line is now recorded in the log file
  1417. X(5/30/87).
  1418. X
  1419. X14) The "KND/IMP" convention of using "CK" to invoke 1K packets during YMODEM
  1420. Xbatch transfers was installed.  This code will be sent during a batch receive 
  1421. Xif "K" is included on the command line unless "M" is also present.  This code
  1422. Xwill be recognized when sending under all circumstances (5/30/87).
  1423. X
  1424. X------------------------------------------------------------------------------
  1425. X
  1426. XChanges leading to version 3.4
  1427. X
  1428. X1) Fix usage message (10/2/87).
  1429. X
  1430. X2) Sender will now try up to 10 times (EOTMAX) to send an EOT to terminate a
  1431. Xtransmission.  Used to be 5 times, but Chuck Forsberg's "official" minimum
  1432. Xrequirements for YMODEM mandate 10 (10/2/87).
  1433. X
  1434. X3) Handle YMODEM file modification times if present in header on reception of
  1435. Xboth binary and text files (10/2/87).  Retracted when can't seem to get
  1436. Xproper times when playing with dsz (10/3/87).  Found bug and reinstalled
  1437. Xfeature (10/16/87).  Found REAL bug (10/21/87).
  1438. X
  1439. X4) Null bytes are now stripped out of files when received as text files (MEX
  1440. Xdoesn't seem to want to put in the terminating control-Z) (10/3/87).
  1441. X
  1442. X5) Slightly modified terminal parameter setting to explicitly turn off CRMOD
  1443. Xand to flush read queue; ideas stolen from Kermit.  Will it fly on Pyramid?
  1444. X(10/3/87).
  1445. X
  1446. X6) Decreased time between "startup" characters sent when starting a file
  1447. Xreceive operation.  This should increase perceived response.  Now waits 
  1448. XWAITFIRST seconds (set to 1) instead of 6 (waits for 5 seconds for 
  1449. Xsubsequent packets.  STERRORMAX now 60, CRCSWMAX now 30.  
  1450. XTimeouts on 1st sector no longer reported in log (10/5/87).
  1451. X
  1452. X7) Once again played with kernel sleeps in readbuf() (packet reading
  1453. Xroutine).  On busy system could cause real problems.  Now supply flag (t)
  1454. Xto suppress sleeping on Too Busy systems.  No longer suppress sleep when
  1455. Xspeeds are over 4800 bps.  Sleep kludge DOES help: on an empty 750 running
  1456. X4.3BSD, a file reception at 2400 bps used 6% of the CPU with the sleep
  1457. Xkludge and 24% without it (data transfer rates were the the same)
  1458. X(10/5/87). 
  1459. X
  1460. X8) Actually count characters as they are being read for a file reception.
  1461. XWhen YMODEM file length is set, stop writing characters when reach length.
  1462. XThis will allow YMODEM file lengths to work for text files and the
  1463. Xelimination of truncfile() in getput.c (which was impossible for SYS V)
  1464. X(10/5/87).
  1465. X
  1466. X9) Another attempt at tty modes.  Now do nothing but set speeds, set mode to
  1467. Xraw, and turn off echoing and tandem (10/6/87).
  1468. X
  1469. X------------------------------------------------------------------------------
  1470. X
  1471. XChanges leading to version 3.5
  1472. X
  1473. X1) Following the suggestion of Bill Carpenter (ho5cad!wjc), I changed every
  1474. Xprintf("") to fprintf(stderr, "") so one can use xmodem on either end of unix
  1475. Xto unix link. (3/24/88).
  1476. X
  1477. X2) Again, thanks to Bill Carpenter, corrected typo in stamptime() in
  1478. Xgetput.sysv.c (3/24/88).
  1479. X
  1480. X3) Thanks to Steve Lebowitz (prcpto!pdvshl), fixed a && that should have been
  1481. Xa & in getput.sysv.c (3/25/88).
  1482. X
  1483. X4) Thanks to Leo Pilachowski, who managed to fool xmodem by "preplacing" ACKS
  1484. Xin the VAX's input queue (improves throughput by 20%, says Leo, but makes
  1485. Xerror recovery a tad dicey...!).  Implemented a flushin() function in
  1486. Xgetput.c to flush any pending characters.  flushin is called in send.c just
  1487. Xafter sending a packet to make sure a proper ACK or NAK is received (I hope 
  1488. Xfast machines don't beat me to it and get their ACKS flushed!).  In
  1489. Xreceive.c, flushin is called prior to the "startup" characters, prior to
  1490. Xsending the packet acknowledgment ACK and prior to the NAK prompting for
  1491. Xconfirming EOT.  Now how does one implement flushin() on Sys V? (3/25/88).
  1492. X
  1493. X5) Fixed pair of bugs in send.c:  YMODEM test enforcing CRC was testing
  1494. Xnumber of attempts against STERRORMAX instead of ERRORMAX (also shortened
  1495. Xtimeout interval on this read) and a "timeout" during packet send was not
  1496. Xnoticed (due to a > instead of a >=) thus program started sending EOTs which
  1497. Xfurther delayed abort (3/28/88).
  1498. X
  1499. X6) Modified send.c and cpmify function in batch.c to strip path names on file
  1500. Xnames transmitted as part of YMODEM batch (3/28/88).
  1501. X
  1502. X7) Hacked receive.c to make end of loop processing clearer and improve
  1503. Xgarbage flushing when errors are detected (3/28/88).
  1504. X
  1505. X8) Pulled out of decision restricting YMODEM batch send to use CRC only.  Will 
  1506. Xnow gladly use checksum if told to and will respond to NAK as well as the 
  1507. Xproper C when starting up data transfer (3/28/88).  Turns out this patch fixes 
  1508. Xproblem with Red Ryder (4/10/88).
  1509. X
  1510. X9) Tested MODEM7 batch against MEX-PC.  Confirmation of EOT during filename
  1511. Xtransmission was not working, so xmodem wasn't shutting down a MODEM7 batch
  1512. Xreceive.  Removed code to NAK first EOT and wait for second EOT in MODEM7
  1513. Xfilename transfers (3/28/88).
  1514. X
  1515. X10) Added code to count number of newlines in a text file to get an accurate
  1516. Xfile size.  I thought it would take too long; but seems to be quite nimble
  1517. X(see countnl in getput.c).  We now transmit YMODEM file length and mode
  1518. Xinformation for text as well as binary files (3/29/88).
  1519. X
  1520. X11) After a YMODEM file name packet was received, forgot to reset "wait" time
  1521. Xfor receiving first character of data packet which definitely slowed
  1522. Xperceived performance.  (See note 6 for v. 3.4).  Fixed (4/7/88).
  1523. X
  1524. X------------------------------------------------------------------------------
  1525. X
  1526. XChanges leading to version 3.6
  1527. X
  1528. X1) Added two new major commands (sa and ra) to send and receive text files
  1529. Xfor Apple Macintoshs which use CR as EOL character instead of the MS/DOS CR
  1530. XLF pair.  Thanks to Dave Nowak (djnowak@iseesun.DPL.SCG.HAC.COM) for the
  1531. Xinspiration (4/11/88).
  1532. X
  1533. X2) Experiences with Red Ryder 10.3.  Fixed botch in receive.c that led to an
  1534. Xinfinite loop when a checksum failed on YMODEM file name packet.  Now have
  1535. Xseperate variables for packet errors and "startup" errors.  Prevent CRC to
  1536. Xchecksum switch during receive startup if YMDMBAT flag is true.  This insures
  1537. Xthat no such transition will ever take place on second or subsequent file
  1538. Xtransfer; can be set on first file by including Y option on command line.  No
  1539. Xlonger print "0" expected sectors if both YMODEM file length and KMD file
  1540. Xlength are both 0 (4/12/88).
  1541. X
  1542. X3) Cleaned up ifs in readbuf.  Removed void declaration on flushin (will
  1543. Xbreak 4.2BSD compiler?).  Corrected "number of sent sectors" on YMODEM
  1544. Xtransfer (was counting filename packet) (4/12/88).
  1545. X
  1546. X4) More experiences with Red Ryder.  Removed line flush before every CRCCHR
  1547. Xor NAK trying to start a receive (RR YMODEM batch send to the VAX now seems
  1548. Xto work).  Fixed KMD "1K reception flag" to work properly on a receive. 
  1549. XAdded a flushin just before program exits in a futile effort to eliminate
  1550. XRR's nasty habit of sending a final EOT down the line.  Rearranged
  1551. Xvariables in send.c so longpackets requested by the KMD flag are not
  1552. X"sticky" from file to file in a batch.  RR is a real DOG: only gets about 133
  1553. Xcps when downloading to a Mac over a 9600 bps line! (4/14/88). 
  1554. X
  1555. X------------------------------------------------------------------------------
  1556. X
  1557. XChanges leading to version 3.7
  1558. X
  1559. X1) More strange and wonderful PC xmodem programs!  Dave Jaksha's program
  1560. Xwon't send send another EOT when first EOT is NAKed.  Raised timeout
  1561. Xthreshold from 3 to 5 seconds and fixed silly bug in receive.c that prevented
  1562. Xany more NAKs from being sent in this situation (5/10/88).
  1563. X
  1564. X------------------------------------------------------------------------------
  1565. X
  1566. XChanges leading to version 3.8
  1567. X
  1568. X1) Added some fields to YMODEM filename record as per Forsberg's revised
  1569. Xspec.  Correct some nits in the way the filename record is handled (11/1/88).
  1570. X
  1571. X------------------------------------------------------------------------------
  1572. X
  1573. XChanges leading to version 3.9
  1574. X
  1575. X1) Better debug message about "packet starting" (10/17/90).
  1576. X
  1577. X2) Added debug error message when readbyte times out (10/17/90).
  1578. X
  1579. X3) Now flush input before ACK of received YMODEM filename packet.
  1580. X(Will this break Red Ryder? Tough.) (10/17/90).
  1581. X
  1582. X4) Now explicitly, after receiving YMODEM filename packet, send NAK or
  1583. XCRCCHR.  Also, check that output file can be opened before ACKING receipt
  1584. Xof YMODEM file name packet.  Both these are required by "True" YMODEM spec.
  1585. XAlso, I think this may cure some of the problems seen with various programs
  1586. Xtrying YMODEM batch transfers. (10/17/90). 
  1587. X
  1588. X5) Added some status messages to be printed to stderr under control of the -P
  1589. Xflag so we can tell the progress of a transfer when invoked with the "~C"
  1590. Xcommand of SunOS tip.  Also added -W flag to slow startup handshake so 
  1591. Xfunny characters don't trash input while one is typing the "~C" command string
  1592. X(via TIPDELAY define, set to 15 seconds).  Utilizes new tlogit and tlogitarg 
  1593. Xmacros. (10/18/90).
  1594. X
  1595. X6) Made a failure to change the mode bits of the tty a non-fatal error
  1596. Xsince, in some systems, uucp owns the device.  Also allows someone who has
  1597. Xsu'd to run Xmodem (10/24/90). 
  1598. X
  1599. X7) Changed error messages about transmissions being canceled "at user's
  1600. Xrequest" to "by CAN-CAN" (10/26/90).
  1601. X
  1602. X8) Go hog-wild with options!  Added "e" option to suppress EOT verification
  1603. Xwhen receiving files (should make some brain-damaged PC programs work with
  1604. Xxmodem).  Added "n" option to allow CAN-CAN aborts any time during a file
  1605. Xtransfer and not just at the beginning.  (10/29/90). 
  1606. X
  1607. X9) Added a one-liner function (stopsig) to getput.c to ignore keyboard stop
  1608. Xsignals so stray ^X characters absorbed during an abort don't put xmodem
  1609. Xinto background!  (10/31/90). 
  1610. X
  1611. X10) Added support for YMODEM-G variant of YMODEM via the "g" flag.
  1612. X(11/1/90).
  1613. X
  1614. X11) Made the "cm" option combination on a receive command force checksum
  1615. X"handshaking" during file-name negotiations and CRC-16 use during file
  1616. Xtransfer.  Why am I still worried about MODEM7?  (11/1/90).
  1617. X
  1618. X12) Revised some status messages to indicate that the option (CRC, 1K
  1619. Xpackets, YMODEM-G) were invoked from the command line rather than through
  1620. X"protocol negotiation."  (11/1/90)
  1621. X
  1622. X13) Don't send "start-up handshake" character when you get a fatal error in a
  1623. Xdata block! (11/2/90)
  1624. X
  1625. X14) Try to REALLY flush input when die with fatal error in data block. 
  1626. XTrying YMODEM-G receptions on a very busy VAX 750 shows up some problems! 
  1627. X(11/2/90). 
  1628. X
  1629. X15) Include a date in the version banner: Version 3.9 (November 1990).
  1630. X(11/5/90).
  1631. X
  1632. X------------------------------------------------------------------------------
  1633. X
  1634. XThanks to Keith Peterson (w8sdz@simtel20.arpa), John Rupley
  1635. X(arizona!rupley!root), Emmet Gray (ihnp4!uiucuxc!fthood!egray), Bob
  1636. XBickford (lll-crg!well!rab), Doug Moore (moore@svax.cs.cornell.edu), David
  1637. XBrown (jdb@ncsc.arpa), Bill Carpenter (ho5cad!wjc), Steve Lebowitz
  1638. X(prcpto!pdvshl), Leo Pilachowski, Dave Nowak
  1639. X(djnowak@iseesun.DPL.SCG.HAC.COM), David Elliot (pyramid!boulder!stan!dce),
  1640. XBenson Margulis (benson@odi.com), Kit Bingham (kb@umnstat.stat.umn.edu),
  1641. XBob Bownes (beowulf!bownes), Bill Stubblebine (hplabs!hp-lsd!was), Chert
  1642. XPellett (spdyne!root) and Chuck Forsberg's documents and ZCOMM/DSZ/rz/sz
  1643. Xprograms for ideas, suggestions and comments.  Thanks to D'Anne Thompson
  1644. Xfor code. 
  1645. END_OF_FILE
  1646.   if test 12797 -ne `wc -c <'update.doc'`; then
  1647.     echo shar: \"'update.doc'\" unpacked with wrong size!
  1648.   fi
  1649.   # end of 'update.doc'
  1650. fi
  1651. echo shar: End of archive 2 \(of 3\).
  1652. cp /dev/null ark2isdone
  1653. MISSING=""
  1654. for I in 1 2 3 ; do
  1655.     if test ! -f ark${I}isdone ; then
  1656.     MISSING="${MISSING} ${I}"
  1657.     fi
  1658. done
  1659. if test "${MISSING}" = "" ; then
  1660.     echo You have unpacked all 3 archives.
  1661.     rm -f ark[1-9]isdone
  1662. else
  1663.     echo You still must unpack the following archives:
  1664.     echo "        " ${MISSING}
  1665. fi
  1666. exit 0
  1667. exit 0 # Just in case...
  1668.